package job.tracker.controller

import java.awt.print.Pageable;
import java.sql.Date;
import java.util.concurrent.TimeUnit;

import job.tracker.domain.*;
import job.tracker.service.*;

import org.jsoup.*;
import org.jsoup.nodes.*;
import org.jsoup.safety.*;
import org.jsoup.select.*;

import geb.*
import geb.waiting.Wait;

import org.openqa.selenium.*
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.*;

import com.gargoylesoftware.htmlunit.*
import com.gargoylesoftware.htmlunit.html.*;
import com.gargoylesoftware.htmlunit.javascript.host.Event;
//
//import com.thoughtworks.selenium.DefaultSelenium;
//import com.thoughtworks.selenium.Selenium;
//
//import grails.plugins.selenium.*;

class SpikerController {

	UtilService utilService
	def browser
	WebDriver driver

	//	def beforeInterceptor = {
	//		println "Tracing action ${actionUri}"
	//		browser = new Browser()
	//		def listener = new EchoingPageChangeListener()
	//		browser.driver = new HtmlUnitDriver(BrowserVersion.FIREFOX_3_6);
	//		browser.driver.setJavascriptEnabled(true);
	//		//browser.driver = new FirefoxDriver()
	//		//browser.driver.javascriptEnabled = true
	//
	//		browser.registerPageChangeListener(listener)
	//	}

	def beforeInterceptor = {
		//driver = new FirefoxDriver()
		//		DesiredCapabilities capabilities = DesiredCapabilities.chrome();
		//		//capabilities.setCapability("chrome.binary", "/opt/google/chrome/chrome");
		//		System.setProperty("webdriver.chrome.driver", "/var/www/chromedriver");
		//		driver = new ChromeDriver(capabilities);
	}

	//def afterInterceptor = { driver.close() }


	def testPost = {
		Map postDataParams = [
					ctl00$MainContent$ASPxRoundPanel1$JobListing1$ddlCareersPerPage:'15'
				];

		//#maincontent-block > table


		Document doc = Jsoup.connect('http://www.serha.gov.jm/(A(uiacWhwMzQEkAAAAOWIwODJiODQtZTNmZi00ZTBhLWFlOTAtN2Q2OTM3MDY1OWIws5Cqfme5wJdUBVh7x9e7sEib28w1))/BrowseVacancies.aspx')
				.userAgent("Mozilla")
				.timeout(10000)
				.data(postDataParams)
				.post();

		render doc.html()
	}



	def testURL = {
		//#maincontent-block > table
		Document doc = Jsoup.connect('http://localhost/dummysite/')
				.userAgent("Mozilla")
				.timeout(10000)
				.get();

		Elements items = doc.select('item')

		render items.size()
	}


	def testHtmlUnit = {
		//final HtmlDivision div = page.getHtmlElementById("some_div_id");
		//final HtmlAnchor anchor = page.getAnchorByName("anchor_name");


		final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3_6);
		webClient.setJavaScriptEnabled(true)
		final HtmlPage page = webClient.getPage("http://www.serha.gov.jm/(A(uiacWhwMzQEkAAAAOWIwODJiODQtZTNmZi00ZTBhLWFlOTAtN2Q2OTM3MDY1OWIws5Cqfme5wJdUBVh7x9e7sEib28w1))/BrowseVacancies.aspx");

		//final String pageAsXml = page.asXml();
		HtmlSelect select = (HtmlSelect) page.getElementById("ctl00_MainContent_ASPxRoundPanel1_JobListing1_ddlCareersPerPage");
		HtmlOption option = select.getOptionByValue("15");
		option.doClickAction()
		option.setSelected(true);
		select.fireEvent(Event.TYPE_CHANGE);
		assert option.isSelected()

		webClient.waitForBackgroundJavaScript(10000);
		webClient.waitForBackgroundJavaScriptStartingBefore(10000)
		println new java.util.Date()
		//final String pageAsText = page.asText();
		println new java.util.Date()
		String elem = page.getElementById("ctl00_MainContent_ASPxRoundPanel1_JobListing1_gvwCareers").asText();
		println new java.util.Date()

		webClient.closeAllWindows();

		render elem
	}

	//FIXME: comment
	def testSite = {
		JobSite jobSite = JobSite.findByName("www.ansamcal.com")
		//jobSite.jobSelector = '> a'
		jobSite.dataElement = '#table29 | tr:eq(1)'
		jobSite.save()

		String out = ''

		List<String> jobs = utilService.scrapeJobs(jobSite);

		out += '<ul>'
		jobs.each { out += "<li>${it}</li>"; }
		out += '</ul>'

		render out
	}

	def gebTest = { println "gebtest" }

	def page2 = { println "page2" }



	def js( String script, driver ){
		(driver as JavascriptExecutor).executeScript( script )
	}

	def testGebOnCF = {

		def out = ''
		out += browser.driver;

		browser.drive {
			go "http://www.yahoo.com/"
			assert title == "Yahoo!"
			$("#p_13838465-p").value("apple");
			$("#search-submit").click()

			//assert title.endsWith("apple")
		}
		render out;
	}

	def testGebOnly = {
		def out = ''


		//		browser.drive {
		//			go "http://www.caribbeanjobs.com/"
		//
		//			$("select[name=Category]").value(3);
		//			$("#btnNavSubmit").click();
		//
		//			assert title.endsWith("IT Jobs - caribbeanjobs.com")
		//		}

		//		browser.drive {
		//			go "http://www.yahoo.com/"
		//			assert title == "Yahoo!"
		//			$("#p_13838465-p").value("apple");
		//			$("#search-submit").click()
		//
		//			assert title.endsWith("apple")
		//		}

		//		browser.drive {
		//			go "http://www.serha.gov.jm/(A(uiacWhwMzQEkAAAAOWIwODJiODQtZTNmZi00ZTBhLWFlOTAtN2Q2OTM3MDY1OWIws5Cqfme5wJdUBVh7x9e7sEib28w1))/BrowseVacancies.aspx"
		//			assert title.endsWith("SERHA - Job Vacancies")
		//			String selct = '#ctl00_MainContent_ASPxRoundPanel1_JobListing1_ddlCareersPerPage'
		//			$(selct).value(15);
		//			assert $(selct).value() == '15'
		//			String trz = "#ctl00_MainContent_ASPxRoundPanel1_JobListing1_gvwCareers > tr"
		//			println $(trz).size()
		//			waitFor(40) {
		//				println $(trz).size()
		//				$(trz).size() > 12
		//			}
		//			$(trz).each {
		//				out += '<br />';
		//				out += it.text()
		//				out += '<br />';
		//			}
		//		}

	}

	def testSelenium = {

		//WebDriver driver = new FirefoxDriver();
		WebDriver driver = browser.driver//new InternetExplorerDriver();

		//String baseUrl = "http://www.serha.gov.jm/";
		String baseUrl = "http://www.caribbeanjobs.com/";

		def selenium = new org.openqa.selenium.WebDriverBackedSelenium(driver, baseUrl);

		selenium.open("/ShowResults.aspx?Category=3&Keywords=Any+Extra+Keywords%3f&x=0&y=0&Page=1");
		java.util.List<WebElement> foundElems = driver.findElements(By.cssSelector("#ctl00_ctl00_cphMain_cphMain_ucJobs_tblJobs tr"))

		java.util.List<WebElement> links = foundElems[0].findElements(By.cssSelector("a"))

		links.each {
			out += '<br />';
			out += it.text
			out += '<br />';
		}

		WebElement nextLink = driver.findElement(By.linkText("[Next >>]"))
		println nextLink
		while (nextLink) {
			selenium.click("link=[Next >>]");
			selenium.waitForPageToLoad("30000");

			foundElems = driver.findElements(By.cssSelector("#ctl00_ctl00_cphMain_cphMain_ucJobs_tblJobs tr"))

			links = foundElems[0].findElements(By.cssSelector("a"))

			links.each {
				out += '<br />';
				out += it.text
				out += '<br />';
			}

			try {
				nextLink = driver.findElement(By.linkText("[Next >>]"))
				println nextLink
			}
			catch (e) {
				nextLink = null
			}

		}
		selenium.close();


		render out


	}

	def testWDSERHA = {
		def out = ''

		String baseUrl = "http://www.serha.gov.jm";

		driver.get(baseUrl + "/(A(uiacWhwMzQEkAAAAOWIwODJiODQtZTNmZi00ZTBhLWFlOTAtN2Q2OTM3MDY1OWIws5Cqfme5wJdUBVh7x9e7sEib28w1))/BrowseVacancies.aspx");
		new Select(driver.findElement(By.cssSelector("#ctl00_MainContent_ASPxRoundPanel1_JobListing1_ddlCareersPerPage"))).selectByVisibleText("15");
		driver.findElement(By.cssSelector("option[value=\"15\"]")).click();

		out += collectJobs(driver, By.id("ctl00_MainContent_ASPxRoundPanel1_JobListing1_gvwCareers"), By.cssSelector(".articletitle > a"))

		render out
	}

	def testWDCJO = {
		def baseUrl = "http://www.caribbeanjobsonline.com"
		driver.get(baseUrl + "/");
		driver.findElement(By.id("p_sectorID_46")).click();
		driver.findElement(By.linkText("Search")).click();
		driver.findElement(By.linkText(">>")).click();
	}

	def testWDCJ = {
		def out = ''

		//url
		//beforeAction(s)
		//jobsContainer
		//jobHeading
		//next page link || resultSize
		println By.id("ctl00_MainContent_ASPxRoundPanel1_JobListing1_gvwCareers")
		println By.id("ctl00_MainContent_ASPxRoundPanel1_JobListing1_gvwCareers").toString()
		return
		println By.id("ctl00_MainContent_ASPxRoundPanel1_JobListing1_gvwCareers").toString() as By
		
		def sites = [
			[
				baseUrl : "http://www.serha.gov.jm/(A(uiacWhwMzQEkAAAAOWIwODJiODQtZTNmZi00ZTBhLWFlOTAtN2Q2OTM3MDY1OWIws5Cqfme5wJdUBVh7x9e7sEib28w1))/BrowseVacancies.aspx",
				beforeAction: [
					[changeSelect : [
							bySelector: By.id("ctl00_MainContent_ASPxRoundPanel1_JobListing1_ddlCareersPerPage"),
							value : "15"
						]],
					[click: By.cssSelector("option[value=\"15\"]")],
				],
				jobsContainer: By.id("ctl00_MainContent_ASPxRoundPanel1_JobListing1_gvwCareers"),
				jobHeading : By.cssSelector(".articletitle > a")
			],
			[
				baseUrl : "http://www.caribbeanjobsonline.com",
				beforeAction: [
					[click: By.id("p_sectorID_46")],
					[click: By.linkText("Search")]
					//[click: By.xpath("/html/body/center/table/tbody/tr/td/table/tbody/tr[5]/td[3]/table/tbody/tr[1]/td/table/tbody/tr[1]/td/table/tbody/tr/td/table/tbody/tr/td/table[@class='tabHeader']/tbody/tr[2]/td[@class='content3']/table[@class='bg_grad']/tbody/tr/td/form[@id='details']/table[@class='tabHeader']/tbody/tr/td[@class='content']/table[@class='bg_grad']/tbody/tr/td/table/tbody/tr[8]/td/a[@class='button']")]
				],
				jobsContainer: By.cssSelector(".content.spacer"),
				jobHeading : By.cssSelector(".Header2 > a"),
				nextLink : By.linkText(">>")
			],
			[
				baseUrl : "http://www.caribbeanjobs.com/ShowResults.aspx?Category=3",
				jobsContainer: By.id("ctl00_ctl00_cphMain_cphMain_ucJobs_tblJobs"),
				jobHeading : By.cssSelector("b > a"),
				nextLink : By.linkText("[Next >>]")
			]
		]

		sites.each { site ->
			driver = new FirefoxDriver()
			//driver.get(site.baseUrl);
			driver.navigate().to(site.baseUrl);

//			driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
//			(new WebDriverWait(driver, 10)).until(new ExpectedCondition<Boolean>() {
//						public Boolean apply(WebDriver d) {
//							//return d.getTitle().toLowerCase().startsWith("it jobs");
//							return d.getCurrentUrl().toLowerCase() == site.baseUrl.toLowerCase()
//						}
//					});

			if (site.beforeAction) {
				site.beforeAction.each { action ->
					action.each { a, actionOpt ->
						switch ( a.toString() ) {
							case "changeSelect":
								new Select(driver.findElement(actionOpt.bySelector)).selectByVisibleText(actionOpt.value);
								break;
							case "click":
								driver.findElement(actionOpt).click();
								break;
						}
					}
				}
			}

			out += collectJobs(driver, site.jobsContainer, site.jobHeading);

			if (site.nextLink) {
				try {
					WebElement nextLink = driver.findElement(site.nextLink);

					while (nextLink != null) {
						nextLink.click()
						out += collectJobs(driver, site.jobsContainer, site.jobHeading);
						nextLink = driver.findElement(site.nextLink);
					}
				}
				catch (NoSuchElementException ex) {
				}
			}
			driver.close()
		}

		render out
	}

	private String collectJobs(WebDriver driver, By jobContainerRef, By actualJob) {
		String out = "";
		WebElement jobsContainer = driver.findElement(jobContainerRef);

		List<WebElement> jobs = jobsContainer.findElements(actualJob)

		out += "<br /><br />${driver.currentUrl} - ${jobs.size()}"
		jobs.each { WebElement job ->
			out += "<br />";
			out += job.getText()
		}
		return out;
	}


	def testSites = {
		List<JobSite> jobSites = JobSite.list()

		String out = ''
		jobSites.each { jobSite ->
			try {
				List<String> jobs = utilService.scrapeJobs(jobSite);

				out += "<h1>${jobSite.pageUrl}</h1>";
				out += "<ul>";
				jobs.each { job ->
					out += "<li>${job}</li>";
				}
				out += "</ul>";
			}
			catch(e) {

			}
		}

		render out
	}
}

class EchoingPageChangeListener implements PageChangeListener {
	void pageWillChange(Browser browser, Page oldPage, Page newPage) {
		println "browser '$browser' changing page from '$oldPage' to '$newPage'"
	}
}

class SelectModule extends Module {

	static content = {
		select { $('select') }
	}

	void set(String value) {

		def element = select.getElement(0)
		def options = element.findElements(By.tagName("option"))

		options.each { WebElement option ->
			if (option.text == value || option.getAttribute('value') == value) {
				option.click()
			}
		}
	}
}